package com.ruoyi.common.utils.ps2;

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

public class ImageBatchProcessor {

    // 记录文件
    private static final String CSV_FILE = "image_processing_log.csv";

    // 进度状态文件
    private static final String PROGRESS_FILE = "progress.state";

    // 支持的图片格式
    private static final Set<String> SUPPORTED_EXTENSIONS = new HashSet<>(Arrays.asList(
            "jpg", "jpeg", "png", "gif", "bmp", "webp"
    ));

    // 起始计数器值
    private static final long START_COUNTER = 30000001L;
    private static final int FILES_PER_FOLDER = 1000;

    // 状态跟踪器
    private static long lastCounter = START_COUNTER;

    // 工作目录（日志和进度文件的存放位置）
    private static Path workspaceDir;

    // 测试用的源文件夹和目标文件夹路径（修改为您自己的路径）
    private static final String TEST_SOURCE_DIR = "E:\\老照片\\老照片";
    private static final String TEST_TARGET_DIR = "E:\\老照片\\批次";

    public static void main(String[] args) {
        try {
            // 1. 检查命令行参数
            Path sourceDir;
            Path targetDir;

            if (args.length >= 2) {
                // 使用命令行参数指定的路径
                sourceDir = Paths.get(args[0]);
                targetDir = Paths.get(args[1]);
                System.out.println("使用命令行参数指定的路径");
            } else {
                // 使用内置测试路径（用于IDEA开发环境）
                sourceDir = Paths.get(TEST_SOURCE_DIR);
                targetDir = Paths.get(TEST_TARGET_DIR);
                System.out.println("使用内置测试路径（开发模式）");
            }

            // 2. 验证源文件夹
            if (!Files.isDirectory(sourceDir)) {
                System.err.println("\n错误: 源文件夹不存在 - " + sourceDir.toAbsolutePath());
                System.err.println("请检查路径是否正确");
                System.exit(1);
            }

            // 3. 确保目标文件夹存在
            Files.createDirectories(targetDir);

            // 4. 设置工作目录（目标文件夹的上一层）
            workspaceDir = targetDir.getParent();
            if (workspaceDir == null) {
                // 如果目标文件夹是根目录，则使用目标文件夹本身
                workspaceDir = targetDir;
            }

            // 5. 设置日志和进度文件路径
            Path logFilePath = workspaceDir.resolve(CSV_FILE);
            Path progressFilePath = workspaceDir.resolve(PROGRESS_FILE);

            System.out.println("\n源文件夹: " + sourceDir.toAbsolutePath());
            System.out.println("目标文件夹: " + targetDir.toAbsolutePath());
            System.out.println("工作目录: " + workspaceDir.toAbsolutePath());
            System.out.println("日志文件: " + logFilePath.toAbsolutePath());
            System.out.println("进度文件: " + progressFilePath.toAbsolutePath());
            System.out.println("文件命名格式: 原图_计数器.扩展名 (计数器从30000001开始)");
            System.out.println("文件夹命名格式: 起始号-结束号 (如: 1-1000)");

            // 6. 加载进度状态（断点续传）
            loadProgressState(progressFilePath);

            // 7. 创建CSV文件
            createCsvFileIfNeeded(logFilePath);

            // 8. 处理图片
            processImages(sourceDir, targetDir, logFilePath, progressFilePath);

            // 9. 保存进度状态
            saveProgressState(progressFilePath);

            System.out.println("\n处理完成！");
            System.out.println("日志文件位置: " + logFilePath.toAbsolutePath());

        } catch (Exception e) {
            System.err.println("\n处理过程中发生错误: " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * 加载进度状态
     */
    private static void loadProgressState(Path progressPath) throws IOException {
        if (Files.exists(progressPath)) {
            try (BufferedReader reader = Files.newBufferedReader(progressPath)) {
                lastCounter = Long.parseLong(reader.readLine());
                System.out.println("检测到上次处理进度，将从断点继续...");
                System.out.println("当前计数器: " + lastCounter);
            }
        } else {
            System.out.println("未找到进度文件，开始新的处理任务");
            lastCounter = START_COUNTER;
        }
    }

    /**
     * 保存进度状态
     */
    private static void saveProgressState(Path progressPath) throws IOException {
        try (BufferedWriter writer = Files.newBufferedWriter(progressPath)) {
            writer.write(String.valueOf(lastCounter));
            System.out.println("进度已保存: " + progressPath);
        }
    }

    /**
     * 创建CSV文件
     */
    private static void createCsvFileIfNeeded(Path logFilePath) throws IOException {
        if (!Files.exists(logFilePath)) {
            try (BufferedWriter writer = Files.newBufferedWriter(logFilePath)) {
                writer.write("原文件路径,新文件路径,原文件名,新文件名,处理时间,文件大小,状态\n");
                System.out.println("已创建新的日志文件: " + logFilePath);
            }
        } else {
            System.out.println("使用现有日志文件: " + logFilePath);
        }
    }

    /**
     * 处理图片的核心方法
     */
    private static void processImages(Path sourceDir, Path targetDir, Path logFilePath, Path progressFilePath) throws IOException {
        System.out.println("\n开始处理图片...");
        System.out.println("起始计数器值: " + lastCounter);

        AtomicLong counter = new AtomicLong(lastCounter);
        long startTime = System.currentTimeMillis();
        final int[] processedCount = {0};
        final int[] skippedCount = {0};
        final int[] errorCount = {0};

        Files.walkFileTree(sourceDir, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
                new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        if (isImageFile(file)) {
                            long currentCount = counter.get();

                            // 计算文件夹名称（1-1000, 1001-2000等格式）
                            String folderName = calculateFolderName(currentCount);
                            Path outputDir = targetDir.resolve(folderName);
                            Files.createDirectories(outputDir);

                            // 获取文件扩展名
                            String extension = getFileExtension(file);

                            // 生成统一命名的新文件名（原图_30000001格式）
                            String newFileName = "原图_" + currentCount + "." + extension;
                            Path outputFile = outputDir.resolve(newFileName);

                            try {
                                if (!Files.exists(outputFile)) {
                                    Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING);
                                    logProcessing(file, outputFile, newFileName, currentCount, logFilePath);
                                    processedCount[0]++;

                                    // 每处理100个文件显示一次进度
                                    if (processedCount[0] % 100 == 0) {
                                        System.out.printf("已处理 %d 个文件，当前计数器: %d%n", processedCount[0], currentCount);
                                        System.out.printf("文件夹: %s, 文件: %s%n", folderName, newFileName);
                                    }
                                } else {
                                    logSkipped(file, outputFile, newFileName, currentCount, logFilePath);
                                    skippedCount[0]++;
                                }

                                // 定期保存进度
                                if (counter.get() % 50 == 0) {
                                    saveProgressState(progressFilePath);
                                }

                            } catch (IOException e) {
                                logError(file, e, currentCount, logFilePath);
                                errorCount[0]++;
                                System.err.println("处理文件失败: " + file + " - " + e.getMessage());
                            }

                            counter.incrementAndGet();
                        }
                        return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult visitFileFailed(Path file, IOException exc) {
                        try {
                            logError(file, exc, counter.get(), logFilePath);
                            errorCount[0]++;
                            System.err.println("访问文件失败: " + file + " - " + exc.getMessage());
                        } catch (IOException e) {
                            System.err.println("无法记录错误到日志文件: " + e.getMessage());
                        }
                        return FileVisitResult.CONTINUE;
                    }
                }
        );

        lastCounter = counter.get();

        long endTime = System.currentTimeMillis();
        long duration = (endTime - startTime) / 1000;

        System.out.println("\n处理结果统计:");
        System.out.println("----------------------------------");
        System.out.printf("成功处理文件数: %d%n", processedCount[0]);
        System.out.printf("跳过文件数: %d%n", skippedCount[0]);
        System.out.printf("处理失败文件数: %d%n", errorCount[0]);
        System.out.printf("总处理时间: %d 秒%n", duration);
        System.out.printf("最终计数器值: %d%n", lastCounter);
        System.out.println("文件命名格式: 原图_计数器.扩展名 (计数器从30000001开始)");
        System.out.println("文件夹命名格式: 起始号-结束号");
        System.out.println("----------------------------------");
    }

    /**
     * 计算文件夹名称（1-1000, 1001-2000等格式）
     */
    private static String calculateFolderName(long counter) {
        // 计算相对序号（从1开始）
        long relativeNumber = counter - 30000000L;

        // 计算当前文件所属的组号（从0开始）
        long groupIndex = (relativeNumber - 1) / FILES_PER_FOLDER;

        // 计算该组的起始和结束编号
        long start = groupIndex * FILES_PER_FOLDER + 1;
        long end = start + FILES_PER_FOLDER - 1;

        return start + "-" + end;
    }

    /**
     * 获取文件扩展名
     */
    private static String getFileExtension(Path file) {
        String fileName = file.getFileName().toString();
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex > 0) {
            return fileName.substring(dotIndex + 1).toLowerCase();
        }
        return "";
    }

    /**
     * 记录错误到日志文件
     */
    private static void logError(Path file, IOException exc, long counter, Path logFilePath) throws IOException {
        String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        String newFileName = "原图_" + counter + "." + getFileExtension(file);
        String record = String.format("\"%s\",\"\",\"%s\",\"%s\",\"%s\",0,\"失败: %s\"%n",
                file.toAbsolutePath(),
                file.getFileName(),
                newFileName,
                timestamp,
                exc.getMessage());

        try (BufferedWriter writer = Files.newBufferedWriter(
                logFilePath, StandardOpenOption.APPEND)) {
            writer.write(record);
        }
    }

    /**
     * 记录跳过的文件
     */
    private static void logSkipped(Path source, Path target, String newFileName, long counter, Path logFilePath) throws IOException {
        String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        String record = String.format("\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",0,\"跳过: 文件已存在\"%n",
                source.toAbsolutePath(),
                target.toAbsolutePath(),
                source.getFileName(),
                newFileName,
                timestamp);

        try (BufferedWriter writer = Files.newBufferedWriter(
                logFilePath, StandardOpenOption.APPEND)) {
            writer.write(record);
        }
    }

    /**
     * 记录处理信息到CSV文件
     */
    private static void logProcessing(Path source, Path target, String newFileName, long counter, Path logFilePath) throws IOException {
        String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        long fileSize = Files.size(source);
        String status = "成功";

        String record = String.format("\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",%d,\"%s\"%n",
                source.toAbsolutePath(),
                target.toAbsolutePath(),
                source.getFileName(),
                newFileName,
                timestamp,
                fileSize,
                status);

        try (BufferedWriter writer = Files.newBufferedWriter(
                logFilePath, StandardOpenOption.APPEND)) {
            writer.write(record);
        }
    }

    /**
     * 判断是否为支持的图片文件
     */
    private static boolean isImageFile(Path file) {
        String fileName = file.getFileName().toString().toLowerCase();
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex > 0) {
            String ext = fileName.substring(dotIndex + 1);
            return SUPPORTED_EXTENSIONS.contains(ext);
        }
        return false;
    }
}